package com.me.test.config;


        
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;

        
@Configuration
@Slf4j
public class RabbitConfig {

  String dlQueueName = "my-queue-dl"; // 普通队列名称
  String dlExchangeName = "my-exchange-dl"; // 死信交换器名称
  String dlRoutingKey  = "rabbit.test";
  String queueName = "retry-queue";
  String exchangeName = "my-exchange"; // 普通交换器名称

  /**
   * 创建死信队列
   * @return
   */
  @Bean
  public Queue queueDL() {
    return QueueBuilder
         .durable(dlQueueName) // 持久化队列
         .build();
   }

   /**
   * 创建死信交换机
   * @return
   */
   @Bean
  public TopicExchange exchangeDL() {
    return new TopicExchange(dlExchangeName, true, false);
   }

  /**
   * 绑定操作
   */
  @Bean
  public Binding bindQueueDL2ExchangeDL(Queue queueDL, TopicExchange exchangeDL) {
    log.info(">>>> 队列与交换器绑定");
    return BindingBuilder.bind(queueDL).to(exchangeDL).with(dlRoutingKey);
   }

   /**
   * 创建持久化队列,同时绑定死信交换器
   * @return
   */
   @Bean
  public Queue queue() {
    log.info(">>>> 创建队列 retry-queue");
    HashMap<String, Object> params = new HashMap<>();
    params.put("x-dead-letter-exchange", dlExchangeName);
    params.put("x-dead-letter-routing-key", dlRoutingKey);

    return QueueBuilder
         .durable(queueName) // 持久化队列
         .withArguments(params) // 关联死信交换器
         .build();
   }

        
   /**
   * 创建交换机
   * @return
   */
  @Bean
  public TopicExchange exchange() {
    log.info(">>>> 创建交换器 my-exchange");
    boolean durable  = true; // 持久化
    boolean autoDelete = false; // 消费者全部解绑时不自动删除
    return new TopicExchange(exchangeName, durable, autoDelete);
   }

  /**
   * 绑定队列到交换机
   * @param queue
   * @param exchange
   * @return
   */
         @Bean
  public Binding bindQueue2Exchange(Queue queue, TopicExchange exchange) {
    log.info(">>>> 队列与交换器绑定");
    return BindingBuilder.bind(queue).to(exchange).with(dlRoutingKey);
   }

//   /**
//   * spring-retry重试机制：当重试次数达到最大，消息仍然消费失败时回调。
//   * 如果开启这个类，则死信队列失效，消息消费失败，即使配置了死信队列，消息也不会进入死信队列。
//   * 重试失败回调和死信队列只能二选一！！！spring 提供回调实现类有如下几个：
//   * RejectAndDontRequeueRecoverer ：消费失败，并且消息不再入列，spring默认使用。
//   * ImmediateRequeueMessageRecoverer ：将消息重新入列
//   * RepublishMessageRecoverer：转发消息到指定的队列，
//   * @return
//   */
//   @Bean
//   public MessageRecoverer messageRecoverer(){
//     return new MessageRecoverer() {
//       @Override
//       public void recover(Message message, Throwable cause) {
//         log.info(message.toString());
//         log.info("spring-retry重试次数达到最大，消息仍然失败的回调");
//         // TODO: 记录错误信息并上报
//       }
//     };
//   }
}
